package jvm.VMExecSubsystem;

/**
 * 方法静态分派演示
 * @author msi
 */
public class StaticDispatch {

    static abstract class Human {
    }

    static class Man extends Human {
    }

    static class Woman extends Human {
    }

    public void sayHello(Human guy) {
        System.out.println("hello,guy!");
    }

    public void sayHello(Man guy) {
        System.out.println("hello,gentleman!");
    }

    public void sayHello(Woman guy) {
        System.out.println("hello,lady!");
    }

    public static void main(String[] args) {
        Human man = new Man();
        Human woman = new Woman();
        StaticDispatch sr = new StaticDispatch();
        sr.sayHello(man);
        sr.sayHello(woman);
    }
}
/**
 * 结果: hello,guy!
 *      hello,guy!
 *      这是因为在 Human man = new Man(); 语句中。我们把 Human 称为变量的 "静态类型(Static Type)"，或者叫 "外观类型(Apparent Type)",后面的 Man 称为变量的"实际类型(Actual Type)".或者叫"运行时类型(Runtime Type)".
 *      静态类型和实际类型在运行中都可能发生变化，区别是静态类型的变化仅仅在使用时发生，变量本身的静态类型不会被改变，并且最终的静态类型是在编译器可知的。
 *      而实际类型变化的结果在运行期才可确定，编译器在编译程序的时候并不知道一个对象的实际类型是什么，(相当于是编译看左边，运行看右边。这句话不是完全正确的，只能作为参考)。
 *      虚拟机(准确来说应该是编译器)在重载时是通过参数的静态类型，而不是动态类型来确定该调用那个方法。所以在上述代码中，其实在编译阶段就已经确定了需要调用那个重载方法(Human的重载方法)。
 *      所有依赖静态类型来决定方法执行版本的分派动作，都成为静态分派。静态分派最典型的例子就是方法的重载。静态分派发生在编译阶段，因此静态分派的动作实际上不是由虚拟机来完成的。
 */
